#include "qbytearrayutil.h"
#include <QString>

namespace kPrivate
{

    static QByteArray toBin(char ch)
    {
        QByteArray ba;
        ba.reserve(8);
        for (int i = 0; i < 8; i++) {
            ba.append(ch & 0x80 ? '1' : '0');
            ch <<= 1;
        }
        return ba;
    }

}
QByteArray QByteArrayUtil::fromHex(QByteArrayView bav)
{
    return QByteArray::fromHex(bav.toByteArray());
}

QByteArray QByteArrayUtil::toHex(QByteArrayView bav)
{
    return bav.toByteArray().toHex();
}


QByteArray QByteArrayUtil::fromBin(QByteArrayView bav)
{
    if (bav.empty())
        return QByteArray();

    QByteArray in(bav.toByteArray());
    while(in.length() % 8)
        in.push_front('0'); // 前面补0

    QByteArray out;
    out.reserve(in.length() / 8);
    for (qsizetype i = 0; i < in.length(); i += 8)
        out.push_back(in.mid(i, 8).toInt(nullptr, 2) & 0xff);

    return out;
}

QByteArray QByteArrayUtil::toBin(QByteArrayView bav)
{
    QByteArray bin;
    bin.reserve(bav.size() * 8);
    for(auto byte : bav)
        bin.append(kPrivate::toBin(byte));
    return bin;
}


QByteArray QByteArrayUtil::fromOct(QByteArrayView bav)
{
    // 先将bav转换为二进制
    QByteArray bin;
    for (auto byte : bav) {
        auto binStr = QString::number(byte - '0', 2);
        assert(binStr.size() <= 3);
        while(binStr.size() < 3)
            binStr.push_front('0');
        bin.push_back(binStr.toLatin1());
    }

    return fromBin(bin);
}

QByteArray QByteArrayUtil::toOct(QByteArrayView bav)
{
    auto bin = toBin(bav);
    while (bin.size() % 3)
        bin.push_front('0');

    QByteArray oct;
    for (qsizetype i = 0; i < bin.size(); i += 3) {
        auto val = bin.mid(i, 3).toInt(nullptr, 2);
        oct.push_back(QString::number(val, 8).toLatin1());
    }

    return oct;
}
